package timeline

import (
	"context"
	"gitee.com/mootok/mootok/src/models"
	"gitee.com/mootok/mootok/src/services/feed"
	"gitee.com/mootok/mootok/src/services/video"
	"gitee.com/mootok/mootok/src/storage/clickhouse"
	"gitee.com/mootok/mootok/src/storage/database"
	"strconv"
	"time"
)

type Service struct {
}

var FeedService feed.Service

const (
	PreferenceTypeCategory int = iota + 1
	PreferenceTypeTag
	PreferenceTypeMarketingCategory
)

func (s *Service) GetHotVideos(amount int, duration time.Duration) ([]int, error) {
	// Get the current time
	now := time.Now()

	threshold := now.Add(-duration)

	var hotVideos []int

	// Query the database using GORM
	err := clickhouse.Client.Model(&models.ReportedVideoPlay{}).
		Select("video_id").
		Where("created_at > ?", threshold).
		Group("video_id").
		Order("COUNT(*) DESC").
		Limit(amount).
		Pluck("video_id", &hotVideos).
		Error
	if err != nil {
		return nil, err
	}
	return hotVideos, nil
}

func (s *Service) GetRandomVideos(amount int) (ids []int, err error) {
	err = database.Client.Model(&models.Video{}).
		Where("status = ?", video.StatusPublished).
		Order("RAND()").Limit(amount).
		Pluck("id", &ids).Error
	return
}

func (s *Service) GetPreferenceCategoryVideos(context context.Context, userId int, amount int, preferenceType int) (ids []int, err error) {
	var categoryIdsStr []string
	err = database.Client.Model(&models.UserPreference{}).
		Where("type = ? AND user_id = ?", preferenceType, userId).
		Order("RAND()").Limit(amount).
		Pluck("value", &categoryIdsStr).Error

	if err != nil {
		return nil, err
	}

	var categoryIds = make([]int, len(categoryIdsStr))
	for index, categoryStr := range categoryIdsStr {
		categoryIds[index], err = strconv.Atoi(categoryStr)
		if err != nil {
			return nil, err
		}
	}
	err = database.Client.Model(&models.VideoCategory{}).
		Where("category_id IN ?", categoryIds).
		Order("RAND()").Limit(amount).
		Pluck("video_id", &ids).
		Error
	return
}

func (s *Service) GetRecommendVideos(context context.Context, amount int, userId int) (ids []int, err error) {
	// 计算每个分类的视频数量
	hotVideoCount := int(float64(amount) * 0.30)
	feedVideoCount := int(float64(amount) * 0.25)
	preferenceVideoCount := int(float64(amount) * 0.35)
	marketingVideoCount := int(float64(amount) * 0.10)

	// 获取热门视频
	hotVideoIds, err := s.GetHotVideos(hotVideoCount, 60 * 24 * time.Hour)
	if err != nil {
		return nil, err
	}

	// 获取关注用户发布的视频
	feedVideoIds, err := FeedService.GetFollowVideoFeed(context, userId, int64(feedVideoCount))
	if err != nil {
		return nil, err
	}

	// 获取偏好视频
	preferenceIds, err := s.GetPreferenceCategoryVideos(context, userId, preferenceVideoCount, PreferenceTypeCategory)
	if err != nil {
		return nil, err
	}

	// 获取营销视频
	marketingVideoIds, err := s.GetPreferenceCategoryVideos(context, userId, marketingVideoCount, PreferenceTypeMarketingCategory)
	if err != nil {
		return nil, err
	}

	// 将所有视频合并为一个推荐列表
	recommendation := append(feedVideoIds, hotVideoIds...)
	recommendation = append(recommendation, preferenceIds...)
	recommendation = append(recommendation, marketingVideoIds...)

	if len(recommendation) < amount {
		randomIds, err := s.GetRandomVideos(amount - len(recommendation))
		if err != nil {
			return nil, err
		}

		recommendation = append(recommendation, randomIds...)
	}

	return recommendation, nil
}
